from constants import *
import random, os, sys
from Tkinter import *

from cpuSched.cpuSched import CPUScheduler
from customSim.newSimulation import NewSimulation
from customSim.loadSimulation import LoadSimulation

#####################################################
#                                                   #
#  AlgoSim class:                                   # 
#                                                   #
#  The AlgoSim class is the primary entry point     #
#  to all program functions such as CPU scheduling, #
#  creating and loading simulations, etc.           #
#                                                   # 
#  Author: Felix Rohrer                             #     
#  Course: CS MET 575                               #
#  Year:   2011                                     #
#                                                   #
#####################################################

class AlgoSim(Frame):
  def __init__(self,master=None):
    Frame.__init__(self,master)
    self.master.title("AlgoSim - Control Menu")
    root.bind_all('<Key>', self.keypress)

    # this variable indicates, if a simulation is
    # currently running. Only one simulation can 
    # run at a time. 
    self.simulationRunning = False

    # create menu bar
    self.makeMenuBar()

    # Create a main frame where all controls go.
    self.ctrlRegion = Frame(master)

    # define which window is currently showing its controls
    self.currentCtrl = None

    # credits window
    self.cr = None 

  # handle keys pressed
  def keypress(self,event):
    if event.keysym == 'Escape':
      if not self.simulationRunning:
        root.destroy()
        return
      else:
        print 'Cannot terminate AlgoSim while simulation running'

  # load main menu for selected function
  # (cpuScheduling, create custom simulation, etc. )
  def showControls(self,name):
    if self.currentCtrl is not None:
      if self.simulationRunning:
        self.currentCtrl.displayInfo("Please stop current simulation first. ")
        return

      # remove previously shown control regions
      items = self.ctrlRegion.children
      for item in items:
	items[item].grid_remove()

      self.currentCtrl.destroy()
      self.currentCtrl = None

    # instanciate correct class
    if name == 'CPUScheduling':
      self.currentCtrl = CPUScheduler(self)
    elif name == 'newSimulation':
      self.currentCtrl = NewSimulation(self)
    elif name == 'loadSimulation':
      self.currentCtrl = LoadSimulation(self)
    self.currentCtrl.controls()

  # create menu bar on top of the main menu
  def makeMenuBar(self):
    # holds the entire menu bar
    topMenu = Menu(self.master)

    # main menu item (open, close, etc)
    menuMain = Menu(topMenu)
    topMenu.add_cascade(label="Main", menu=menuMain)
    menuMain.add_command(label="New simulation", command=lambda: self.showControls('newSimulation'))
    menuMain.add_command(label="Load simulation", command=lambda: self.showControls('loadSimulation'))
    menuMain.add_command(label="Close", command=self.quit)

    # lambda function is used as a link between Tkinter and showControls function
    # menu item to select scheduling algorithms
    menuCPU = Menu(topMenu)
    topMenu.add_cascade(label="Scheduling", menu=menuCPU)
    menuCPU.add_command(label="CPU Scheduling", command=lambda: self.showControls('CPUScheduling'))

    # menu item to select virtual memory algorithms
    menuVirt = Menu(topMenu)
    topMenu.add_cascade(label="Virtual Memory", menu=menuVirt)
    menuVirt.add_command(label="Page replacement", command=lambda: self.showControls('PageReplacement'), state=DISABLED)

    # menu item to select Deadlock algorithms/problems
    menuDead = Menu(topMenu)
    topMenu.add_cascade(label="Deadlocks", menu=menuDead)
    menuDead.add_command(label="Dining Philosophers", state=DISABLED)

    # menu item to select Deadlock algorithms/problems
    menuHelp = Menu(topMenu)
    topMenu.add_cascade(label="Help", menu=menuHelp)
    menuHelp.add_command(label="Credits", command=self.credits)

    # make the menu bar visible
    self.master.config(menu=topMenu)
    return 

  def quit(self):
    if self.simulationRunning:
      self.currentCtrl.displayInfo("Please stop current simulation first. ")
      return
    self.currentCtrl.destroy()
    # terminate
    sys.exit(0)

  # show credits window
  def credits(self):
    # function to close credits window
    def closeCredits():
      self.cr.withdraw()

    # if credit window does not yet exist
    # create it
    if self.cr is None:
      self.cr = Toplevel(bg='#D9D9D9',bd=1,relief=RAISED)
      self.cr.title("Credits")
      self.cr.geometry('150x100+300+150')
      self.cr.resizable(0,0)
      self.cr.overrideredirect(True)

      Label(self.cr, text='').pack()
      Label(self.cr, text='BU MET 2011', justify=CENTER, bg='#8888EE',relief=GROOVE, width=15).pack()
      Label(self.cr, text="felixro@bu.edu", justify=CENTER, bg='#EE8888',relief=GROOVE, width=15).pack()
      Label(self.cr, text='').pack()
      Button(self.cr, text="Close", command=closeCredits).pack()
    # otherwise simply redisplay the credit window
    else:
      self.cr.deiconify()

# main entry function into this application
if __name__ == "__main__":
  root = Tk(className='AlgoSim')
  k=AlgoSim(master=root)
  root.geometry(MAINMENU_DIM)
  root.mainloop()
